package com.unionpay.rpc;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URL;

import org.apache.log4j.Logger;

import com.unionpay.config.Config;
import com.unionpay.util.JSON;

/**
 * 请求RPC服务器
 * 
 * @author liuzy
 * @since 2016年4月29日
 */
public class Rpc {
	private static Logger logger = Logger.getLogger(Rpc.class);
	public static final String ETH_ACCOUNTS = "eth_accounts";
	public static final String ETH_SENDTRANSACTION = "eth_sendTransaction";
	public static final String ETH_GETTRANSACTIONBYHASH = "eth_getTransactionByHash";
	public static final String WEB3_SHA3 = "web3_sha3";
	
	public static final String ETH_PROTOCOLVERSION = "eth_protocolVersion";
	public static final String WEB3_CLIENTVERSION = "web3_clientVersion";
	public static final String NET_VERSION = "net_version";
	public static final String NET_LISTENING = "net_listening";
	public static final String ETH_SYNCING = "eth_syncing";
	public static final String ETH_MINING = "eth_mining";
	public static final String ETH_HASHRATE = "eth_hashrate";
	public static final String ETH_COINBASE = "eth_coinbase";
	public static final String ETH_BLOCKNUMBER = "eth_blockNumber";
	public static final String ETH_GETBLOCKBYHASH = "eth_getBlockByHash";
	public static final String ETH_GETBLOCKBYNUMBER = "eth_getBlockByNumber";
	public static final String ETH_GETBLOCKTRANSACTIONCOUNTBYHASH = "eth_getBlockTransactionCountByHash";
	public static final String ETH_GETBLOCKTRANSACTIONCOUNTBYNUMBER = "eth_getBlockTransactionCountByNumber";
	public static final String ETH_GETTRANSACTIONCOUNT = "eth_getTransactionCount";
	
	
	private static int timeout = 5000;
	private static String charset = "UTF-8";

	public static Data request(RpcMethod method) {
		return request(Config.PUBLIC_RPC, method);
	}

	public static Data request(String rpcUrl, RpcMethod method) {
		HttpURLConnection conn = null;
		OutputStream ous = null;
		InputStream ins = null;
		Reader reader = null;
		try {
			URL uri = new URL(rpcUrl);
			conn = (HttpURLConnection) uri.openConnection();
			conn.setRequestMethod("POST");
			conn.setConnectTimeout(timeout);
			conn.setReadTimeout(timeout);
			conn.setUseCaches(false);
			conn.addRequestProperty("Content-Type", "application/json");
			if (method != null) {
				conn.setDoOutput(true);
				ous = conn.getOutputStream();
				String body = JSON.toJson(method);
				logger.info("RPC -> " + rpcUrl + " " + body);
				ous.write(body.getBytes());
				ous.flush();
			}
			conn.connect();
			ins = conn.getInputStream();
			reader = new InputStreamReader(ins, charset);
			StringBuffer buffer = new StringBuffer();
			char[] tmp = new char[1024];
			int len;
			while ((len = reader.read(tmp)) != -1) {
				buffer.append(tmp, 0, len);
			}
			String response = buffer.substring(0, buffer.length() - 1).toString();
			logger.info("RPC <- " + response);
			Data data = null;
			if (response.contains("error")) {
				data = JSON.fromJson(response, Data.class);
			} else if (response.contains("result\":[")) {
				data = JSON.fromJson(response, DataArr.class);
			} else if (response.contains("result\":{")) {
				data = JSON.fromJson(response, DataObj.class);
			} else {
				data = JSON.fromJson(response, DataStr.class);
			}
			return data;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			conn.disconnect();
			try {
				if (ous != null) {
					ous.close();
				}
				if (ins != null) {
					ins.close();
				}
				if (reader != null) {
					reader.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return null;
	}
}
